import { useCallback, useEffect, useState } from 'react';
import { AuthContext } from '@/auth/context/auth-context';
import * as authHelper from '@/auth/lib/helpers';
import { authService } from '@/lib/api/services/auth-service.js';

const ACCESS_TOKEN_KEY = 'auth_token';
const REFRESH_TOKEN_KEY = 'auth_refresh_token';

const persistTokens = (auth) => {
  if (typeof window === 'undefined') return;
  if (auth?.accessToken) {
    localStorage.setItem(ACCESS_TOKEN_KEY, auth.accessToken);
    sessionStorage.setItem(ACCESS_TOKEN_KEY, auth.accessToken);
  } else {
    localStorage.removeItem(ACCESS_TOKEN_KEY);
    sessionStorage.removeItem(ACCESS_TOKEN_KEY);
  }

  if (auth?.refreshToken) {
    localStorage.setItem(REFRESH_TOKEN_KEY, auth.refreshToken);
  } else {
    localStorage.removeItem(REFRESH_TOKEN_KEY);
  }
};

const clearTokens = () => {
  if (typeof window === 'undefined') return;
  localStorage.removeItem(ACCESS_TOKEN_KEY);
  sessionStorage.removeItem(ACCESS_TOKEN_KEY);
  localStorage.removeItem(REFRESH_TOKEN_KEY);
};

const normalizeAuthResponse = (response) => {
  if (!response) return null;
  const accessToken = response.accessToken || response.access_token;
  const refreshToken = response.refreshToken || response.refresh_token;
  const expiresInSec = Number(response.expiresIn || response.expires_in || 0);
  const expiresAt = expiresInSec ? Date.now() + expiresInSec * 1000 : null;
  const user =
    response.user ||
    (response.data && response.data.user) ||
    response.account ||
    null;

  return {
    accessToken,
    refreshToken,
    tokenType: response.tokenType || response.token_type || 'Bearer',
    expiresIn: expiresInSec || null,
    expiresAt,
    user,
  };
};

export function AuthProvider({ children }) {
  const [loading, setLoading] = useState(true);
  const [auth, setAuthState] = useState(authHelper.getAuth());
  const [currentUser, setCurrentUser] = useState(auth?.user);
  const [isAdmin, setIsAdmin] = useState(false);

  useEffect(() => {
    const stored = authHelper.getAuth();
    if (stored) {
      setAuthState(stored);
      setCurrentUser(stored.user || undefined);
      persistTokens(stored);
    }
    setLoading(false);
  }, []);

  useEffect(() => {
    const roleName = currentUser?.roleName || currentUser?.role?.name;
    setIsAdmin(
      Boolean(
        currentUser?.is_admin === true ||
          (typeof roleName === 'string' && roleName.toUpperCase() === 'ADMIN'),
      ),
    );
  }, [currentUser]);

  const saveAuth = useCallback((nextAuth) => {
    setAuthState(nextAuth || undefined);
    if (nextAuth) {
      authHelper.setAuth(nextAuth);
      persistTokens(nextAuth);
    } else {
      authHelper.removeAuth();
      clearTokens();
    }
  }, []);

  const login = useCallback(
    async (email, password) => {
      try {
        const response = await authService.login({ email, password });
        if (typeof import.meta !== 'undefined' && import.meta.env?.DEV) {
          // eslint-disable-next-line no-console
          // console.log('[Auth] login response:', response);
        }
        const normalized = normalizeAuthResponse(response);
        if (!normalized?.accessToken) {
          throw new Error('登录失败，未获取到访问令牌');
        }
        if (typeof import.meta !== 'undefined' && import.meta.env?.DEV) {
          // eslint-disable-next-line no-console
          // console.log('[Auth] normalized auth:', normalized);
        }
        saveAuth(normalized);
        setCurrentUser(normalized.user || undefined);
        return normalized.user || null;
      } catch (error) {
        saveAuth(undefined);
        setCurrentUser(undefined);
        if (error instanceof Error) {
          throw error;
        }
        throw new Error('登录失败，请稍后重试');
      }
    },
    [saveAuth],
  );

  const register = useCallback(
    async (...args) => {
      let payload = args[0];

      if (args.length !== 1 || typeof payload !== 'object' || Array.isArray(payload)) {
        const [
          email,
          password,
          passwordConfirmation,
          firstName,
          lastName,
        ] = args;

        if (!email || !password) {
          throw new Error('邮箱和密码不能为空');
        }

        if (password !== passwordConfirmation) {
          throw new Error('两次输入的密码不一致');
        }

        const defaultUsername =
          (typeof email === 'string' && email.includes('@')
            ? email.split('@')[0]
            : `user${Date.now()}`);
        const fullName = [firstName, lastName].filter(Boolean).join(' ').trim();

        payload = {
          email,
          password,
          username: defaultUsername,
          fullName: fullName || defaultUsername,
        };
      }

      const response = await authService.register(payload);
      const normalized = normalizeAuthResponse(response);
      if (!normalized?.accessToken) {
        throw new Error('注册失败，未获取到访问令牌');
      }
      saveAuth(normalized);
      setCurrentUser(normalized.user || undefined);
      return normalized.user || null;
    },
    [saveAuth],
  );

  const verify = useCallback(async () => {
    const stored = authHelper.getAuth();
    if (typeof import.meta !== 'undefined' && import.meta.env?.DEV) {
      // eslint-disable-next-line no-console
      console.log('[Auth] verify stored auth:', stored);
      // eslint-disable-next-line no-console
      console.log('[Auth] verify tokens:', stored?.accessToken, stored?.refreshToken);
    }
    if (!stored?.accessToken) {
      saveAuth(undefined);
      setCurrentUser(undefined);
      return null;
    }
    setAuthState(stored);

    const shouldRefresh =
      Boolean(stored.refreshToken) &&
      (!stored.expiresAt || Date.now() > stored.expiresAt - 60 * 1000);

    if (typeof import.meta !== 'undefined' && import.meta.env?.DEV) {
      // eslint-disable-next-line no-console
      console.log('[Auth] verify shouldRefresh:', shouldRefresh, {
        now: Date.now(),
        expiresAt: stored.expiresAt,
      });
    }

    if (!shouldRefresh) {
      setCurrentUser(stored.user || undefined);
      return stored.user || null;
    }

    try {
      const refreshed = await authService.refresh(stored.refreshToken);
      const normalized = normalizeAuthResponse(refreshed);
      if (!normalized?.accessToken) {
        throw new Error('刷新令牌失败');
      }
      saveAuth(normalized);
      setCurrentUser(normalized.user || undefined);
      return normalized.user || null;
    } catch (error) {
      saveAuth(undefined);
      setCurrentUser(undefined);
      if (typeof import.meta !== 'undefined' && import.meta.env?.DEV) {
        // eslint-disable-next-line no-console
        console.error('[Auth] refresh token failed:', error);
      }
      return null;
    }
  }, [saveAuth]);

  const getUser = useCallback(async () => {
    const stored = authHelper.getAuth();
    if (stored?.user) {
      return stored.user;
    }
    try {
      const user = await verify();
      return user;
    } catch {
      return null;
    }
  }, [verify]);

  const logout = useCallback(async () => {
    try {
      await authService.logout();
    } finally {
      saveAuth(undefined);
      setCurrentUser(undefined);
    }
  }, [saveAuth]);

  const requestPasswordReset = useCallback(async (email) => {
    if (!email) {
      throw new Error('邮箱不能为空');
    }
    return authService.requestPasswordReset(email);
  }, []);

  const resetPassword = useCallback(async ({ token, newPassword }) => {
    if (!token || !newPassword) {
      throw new Error('重置令牌和新密码不能为空');
    }
    return authService.resetPassword({ token, newPassword });
  }, []);

  const changePassword = useCallback(async ({ currentPassword, newPassword }) => {
    if (!currentPassword || !newPassword) {
      throw new Error('当前密码和新密码不能为空');
    }
    return authService.changePassword({ currentPassword, newPassword });
  }, []);

  const resendVerificationEmail = useCallback(() => {
    return Promise.reject(
      new Error('当前系统未启用邮箱验证流程，请联系管理员。'),
    );
  }, []);

  const updateProfile = useCallback(() => {
    return Promise.reject(new Error('当前系统暂不支持前端编辑个人资料。'));
  }, []);

  return (
    <AuthContext.Provider
      value={{
        loading,
        setLoading,
        auth,
        saveAuth,
        user: currentUser,
        setUser: setCurrentUser,
        login,
        register,
        requestPasswordReset,
        resetPassword,
        resendVerificationEmail,
        changePassword,
        getUser,
        updateProfile,
        logout,
        verify,
        isAdmin,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
}

